package com.lxl.microservicesimleconsumermovie.feign;

import com.lxl.microservicesimleconsumermovie.config.FeignLogConfiguration;
import com.lxl.microservicesimleconsumermovie.entity.User;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

/**
 * @desc: 请求用户服务的feign接口 (下面有对应的回退类)
 * @date & @author: 2018/11/20 17:31 & lxl
 */
// @FeignClient(name = "microservice-provider-user-my-metadata", configuration = FeignConfiguration.class)
@FeignClient(name = "microservice-provider-user-my-metadata", fallbackFactory = FeignClientFallbackFactory.class)
public interface UserFeignClient {

    /**
     * 根据id查找用户
     *
     * @param id 用户id
     * @return User
     */
    // 使用SpringMVC注解
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    User findById(@PathVariable("id") Long id);

    // 使用Feign的注解
    // @RequestLine("GET /{id}")
    // User findById(@Param("id") Long id);


    @RequestMapping(value = "/{id}/{name}", method = RequestMethod.GET)
    User getUserByIdAndNamePathVariableGet(@PathVariable("id") Long id, @PathVariable("name") String name);

    @RequestMapping(value = "/{id}/{name}", method = RequestMethod.POST)
    User getUserByIdAndNamePathVariablePost(@PathVariable("id") Long id, @PathVariable("name") String name);


    @RequestMapping(value = "/user", method = RequestMethod.GET)
    User getUserByIdAndNameRequestParamGet(@RequestParam("id") Long id, @RequestParam("name") String name);

    @RequestMapping(value = "/user", method = RequestMethod.GET)
    User getUserByIdAndNameRequestParamMap(@RequestParam Map<String, Object> map);

    @RequestMapping(value = "/user/entity", method = RequestMethod.POST)
    User getUserPostJson(@RequestBody User user);
}


/**
 * @desc: feign和hystrix整合后的回退类
 * @date & @author: 2018/11/26 14:51 & lxl
 */
@Component
class FeignClientFallback implements UserFeignClient {

    @Override
    public User findById(Long id) {
        User user = new User();
        user.setName("feign和hystrix整合的回退类");
        return user;
    }

    @Override
    public User getUserByIdAndNamePathVariableGet(Long id, String name) {
        return null;
    }

    @Override
    public User getUserByIdAndNamePathVariablePost(Long id, String name) {
        return null;
    }

    @Override
    public User getUserByIdAndNameRequestParamGet(Long id, String name) {
        return null;
    }

    @Override
    public User getUserByIdAndNameRequestParamMap(Map<String, Object> map) {
        return null;
    }

    @Override
    public User getUserPostJson(User user) {
        return null;
    }
}

/**
 * @desc: feign和hystrix整合后(可以在里面打印回退日志等操作)
 * @date & @author: 2018/11/26 15:39 & lxl
 */
@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
    private static final Logger logger = LoggerFactory.getLogger(FeignClientFallbackFactory.class);

    @Override
    public UserFeignClient create(Throwable throwable) {
        return new UserFeignClient() {
            @Override
            public User findById(Long id) {

                logger.info("fallback, reason was: {}", throwable.getMessage());

                User user = new User();
                user.setName("feign和hystrix整合的回退类(带日志打印)");
                return user;
            }

            @Override
            public User getUserByIdAndNamePathVariableGet(Long id, String name) {
                return null;
            }

            @Override
            public User getUserByIdAndNamePathVariablePost(Long id, String name) {
                return null;
            }

            @Override
            public User getUserByIdAndNameRequestParamGet(Long id, String name) {
                return null;
            }

            @Override
            public User getUserByIdAndNameRequestParamMap(Map<String, Object> map) {
                return null;
            }

            @Override
            public User getUserPostJson(User user) {
                return null;
            }
        };
    }
}